# -*- coding: utf-8 -*-#
__author__ = 'yangq'
import random

from tornado import gen
from appcommon.appinstance import mysql_app_pool
from common import timetool
from random import Random
import hashlib
import time
import base64
import datetime
import random
import hashlib
import urllib
import urllib2
import rsa
from xml.etree import ElementTree
import ssl
from settings import PAY_TYPE, ALI_PARTNER
from user import models as userm
from couch import models as couchm
import settings
import json
from appcommon.httputil import get_request_data


def create_out_trade_no(phone):
    str = timetool.get_datetime()
    m = hashlib.md5()
    m.update(phone + str)
    return m.hexdigest()


@gen.coroutine
def get_order_with_phone(phone, order_type):
    sql = (
        "select phone, out_trade_no, total_fee, create_time from pay_order where phone = '{}' "
        "and order_type = '{}'"
        "and status in (0, 1)"
    )
    res = yield mysql_app_pool.get_all(sql.format(phone, order_type), cursor='dict')
    raise gen.Return(res)


@gen.coroutine
def del_old_order(out_trade_no):
    sql = (
        "delete from pay_order where out_trade_no = '{}' "
        "and status in (0, 1)"
    )
    res = yield mysql_app_pool.delete(sql.format(out_trade_no))
    raise gen.Return(res)


@gen.coroutine
def get_order_with_out(out_trade_no):
    sql = (
        "select * from pay_order where out_trade_no = '{}' and status = 0"
    )
    res = yield mysql_app_pool.get_one(sql.format(out_trade_no), cursor='dict')
    raise gen.Return(res)


@gen.coroutine
def insert_order_2_mysql(order_info, from_phone):
    sql = (
        "insert into pay_order (phone, out_trade_no, total_fee, body, status, create_time, from_phone, order_type) values "
        u"('{}', '{}', {}, '{}', 0, {}, '{}', '{}')"
    )
    if order_info['order_type'] == 'vip1':
        body = u'开通科目一VIP'
    elif order_info['order_type'] == 'vip4':
        body = u'开通科目四VIP'
    else:
        body = u'开通报名通'
    res = yield mysql_app_pool.insert_one(sql.format(
        order_info['phone'],
        order_info['out_trade_no'],
        order_info['total_fee'],
        body,
        order_info['create_time'],
        from_phone,
        order_info['order_type']
    ))
    raise gen.Return(res)


# 生成nonce_str
def getnonce_str():
    nowdt = str(int(time.time()))
    randomstr = str(random.randint(1000,9999))
    nonce_str = ''.join([nowdt, randomstr])
    return nonce_str


def wx_get_pre_order_id(phone, out_trade_no, total_fee, pay_type, openid, body):
    trada_info = PAY_TYPE[pay_type]
    # 签名时用到的字典
    param_dic = {'appid': trada_info["appid"],
                 'mch_id': trada_info["mch_id"],
                 'nonce_str': getnonce_str(),
                 'attach': phone,  # 附加数据
                 'body': body[0:20],  # 商品描述
                 'detail': "",  # 商品详情
                 'out_trade_no': out_trade_no,
                 'fee_type': 'CNY',
                 'total_fee': total_fee,
                 'spbill_create_ip': "47.92.112.59",
                 'notify_url': 'http://app.qcjkjg.com/wxnotify',
                 'trade_type': trada_info["trade_type"]
                 }
    # 公众号必须带openid参数
    open_id = ''
    if pay_type == 'gzh':
        param_dic['openid'] = openid
        open_id = '<openid>' + openid.encode('utf-8') + '</openid>'
    signStr = creatsig_md5(param_dic, trada_info["signkey"])
    # 向微信服务器发送的xml文档
    xmlData = '''<xml>
                           <appid>''' + param_dic['appid'] + '''</appid>
                           <mch_id>''' + param_dic['mch_id'] + '''</mch_id>
                           <attach>''' + param_dic['attach'].encode('utf-8') + '''</attach>
                           <nonce_str>''' + param_dic['nonce_str'] + '''</nonce_str>
                           <body>''' + param_dic['body'].encode('utf-8') + '''</body>
                           <detail>''' + param_dic['detail'].encode('utf-8') + '''</detail>
                           <out_trade_no>''' + param_dic['out_trade_no'].encode('utf-8') + '''</out_trade_no>
                           <fee_type>''' + param_dic['fee_type'] + '''</fee_type>
                           <total_fee>''' + param_dic['total_fee'].encode('utf-8') + '''</total_fee>
                           <spbill_create_ip>''' + param_dic['spbill_create_ip'] + '''</spbill_create_ip>
                           <notify_url>''' + param_dic['notify_url'] + '''</notify_url>
                           <trade_type>''' + param_dic['trade_type'] + '''</trade_type>
                           ''' + open_id + '''
                           <sign>''' + signStr + '''</sign>
                        </xml>'''
    request_object = urllib2.Request('https://api.mch.weixin.qq.com/pay/unifiedorder', xmlData)
    context = ssl._create_unverified_context()
    response = urllib2.urlopen(request_object, context=context)
    # 将返回的xml数据转换成字典
    xmlresult = response.read()
    xdict = xmltodict(xmlresult, trada_info["signkey"])
    return xdict


def creatsig_rsa(dicx):
    with open('rsa_private_key.pem') as privatefile:
        p = privatefile.read()
        privkey = rsa.PrivateKey.load_pkcs1(p)
    signature = rsa.sign(dicx, privkey, 'SHA-256')
    return urllib.quote(base64.b64encode(signature), safe='')


def ali_get_pre_order_id(phone, out_trade_no, total_fee, body):
    # 签名时用到的字典
    timestamp = timetool.get_current_datetime()
    biz_content = {
        "timeout_express": "30m",
        "product_code": "QUICK_MSECURITY_PAY",
        "total_amount": total_fee,
        "subject": body,
        "body": phone,
        "out_trade_no": out_trade_no
    }
    param_dict = dict(
        app_id=ALI_PARTNER['appid'],
        biz_content=json.dumps(biz_content, ensure_ascii=False),
        charset="utf-8",
        format="json",
        method="alipay.trade.app.pay",
        notify_url="http://app.qcjkjg.com/alinotify",
        sign_type="RSA2",
        timestamp=timestamp,
        version="1.0"

        # timeout_express="30m",
        # product_code="QUICK_MSECURITY_PAY",
        # total_amount=total_fee,
        # subject=u"开通VIP",
        # body=u"开通VIP",
        # out_trade_no=out_trade_no
    )
    urlstr = ""
    a = sorted(param_dict.keys())
    for item in a:
        urlstr += u'&{}={}'.format(item, param_dict[item])
    urlstr = urlstr[1:]
    signStr = creatsig_rsa(urlstr.encode('utf-8'))
    # dict_app = dict(urlstr=urlstr, sign=signStr)
    # dict_result = dict(code='0', info=dict_app)
    res = urlstr + '&sign=' + signStr

    dict_result = dict(code='0', info=res)
    return dict_result


def xmltodict(xmlstr,signkey):
    root = ElementTree.fromstring(xmlstr)
    return_code = root.find('return_code')
    result_code = root.find('result_code')
    prepay_id = root.find('prepay_id')
    if return_code.text=='SUCCESS' :
        appid = root.find('appid')
        mch_id = root.find('mch_id')
        nonce_str = root.find('nonce_str')
        sign = root.find('sign')

    if return_code.text=='SUCCESS' and result_code.text=='SUCCESS' :
        trade_type = root.find('trade_type')
        prepay_id = root.find('prepay_id')
        if trade_type.text == 'JSAPI':
            APPdict = dict(appId=appid.text, signType='MD5', package='prepay_id={}'.format(prepay_id.text),
                           nonceStr=getnonce_str(), timeStamp=str(int(time.time())))
        else:
            APPdict= dict(appid=appid.text,partnerid=mch_id.text,prepayid=prepay_id.text,
                          package='Sign=WXPay',noncestr=getnonce_str(),timestamp=str(int(time.time())))
        APPsign=creatsig_md5(APPdict,signkey)
        APPdict['sign']=APPsign
        resultdict=dict(code='0',info=APPdict)
        return resultdict
    else:
        if root.find('err_code_des') is not None:
            resultdict=dict(code='1002',msg=root.find('err_code_des').text)
        else:
            resultdict=dict(code='1002',msg=root.find('return_msg').text)
        return resultdict


def creatsig_md5(dicx,signkey):
    dict= sorted(dicx.iteritems(), key=lambda d:d[0])
    stringA=""
    for (k,v) in  dict:
        if v:
            stringA+="%s=%s&"%(k,v.encode('utf-8'))
    stringSignTemp=stringA+'key='+signkey
    md5Sign=hashlib.md5(stringSignTemp).hexdigest()
    return md5Sign.upper()


@gen.coroutine
def add_score_open_vip(phone):
    current_time = timetool.get_timestamp()
    # score_type = self.get_argument('score_type', '2')  # 1: 分享后开通vip  2：分享
    # 开通vip逻辑
    from_phone = yield userm.get_from_phone(phone)
    if from_phone:
        is_vip = yield userm.check_phone_is_vip(from_phone, current_time)
        is_couch = yield userm.check_phone_is_couch(from_phone)
        if is_vip == "1" or is_couch == "1":
            # add_socre = settings.ADD_SCORE['student_vip'] if user_type == '0' else settings.ADD_SCORE['teacher_vip']
            user_type = "couch" if is_couch == "1" else "other"
            add_socre = yield userm.get_score_from_score_conf(user_type, 'open_vip')
            yield userm.update_score_2_mysql(from_phone, 'add', add_socre)
            yield userm.save_score_log(from_phone, add_socre, '1', current_time, phone)
        else:
            pass
    else:
        pass
    raise gen.Return(1)


@gen.coroutine
def open_vip1(phone):
    start = timetool.get_timestamp()
    end1 = timetool.get_before_or_after_date(30, 1)
    end = timetool.convert_date_to_timestamp(end1 + " 23:59:59")
    # score_type = self.get_argument('score_type', '2')  # 1: 分享后开通vip  2：分享
    # 开通vip逻辑
    sql = "select 1 from app_vip_user where phone = '{}'"
    phone_exist = yield mysql_app_pool.get_one(sql.format(phone))
    if phone_exist:
        sql_u = "update app_vip_user set start={}, end={} where phone = '{}'"
        yield mysql_app_pool.update(sql_u.format(start, end, phone))
    else:
        sql_i = "insert into app_vip_user (phone, start, end) values ('{}', {}, {})"
        yield mysql_app_pool.insert_one(sql_i.format(phone, start, end))
    raise gen.Return(1)


@gen.coroutine
def open_vip4(phone):
    start = timetool.get_timestamp()
    end1 = timetool.get_before_or_after_date(30, 1)
    end = timetool.convert_date_to_timestamp(end1 + " 23:59:59")
    # score_type = self.get_argument('score_type', '2')  # 1: 分享后开通vip  2：分享
    # 开通vip逻辑
    sql = "select 1 from app_vip4_user where phone = '{}'"
    phone_exist = yield mysql_app_pool.get_one(sql.format(phone))
    if phone_exist:
        sql_u = "update app_vip4_user set start={}, end={} where phone = '{}'"
        yield mysql_app_pool.update(sql_u.format(start, end, phone))
    else:
        sql_i = "insert into app_vip4_user (phone, start, end) values ('{}', {}, {})"
        yield mysql_app_pool.insert_one(sql_i.format(phone, start, end))
    raise gen.Return(1)


@gen.coroutine
def open_bmt(phone):
    start = timetool.get_timestamp()
    end1 = timetool.get_before_or_after_date(365, 1)
    end = timetool.convert_date_to_timestamp(end1 + " 23:59:59")
    # score_type = self.get_argument('score_type', '2')  # 1: 分享后开通vip  2：分享
    # 开通vip逻辑
    sql = "select 1 from couch_bmt where phone = '{}'"
    phone_exist = yield mysql_app_pool.get_one(sql.format(phone))
    if phone_exist:
        sql_u = "update couch_bmt set start={}, end={} where phone = '{}'"
        yield mysql_app_pool.update(sql_u.format(start, end, phone))
    else:
        sql_i = "insert into couch_bmt (phone, start, end) values ('{}', {}, {})"
        yield mysql_app_pool.insert_one(sql_i.format(phone, start, end))
    raise gen.Return(1)


@gen.coroutine
def check_ali_notify_auth(resultdict):
    raise gen.Return(1)


@gen.coroutine
def update_order_status(out_trade_no, status, pay_type):
    sql = "update pay_order set status = {}, pay_type = '{}' where out_trade_no = '{}'"
    yield mysql_app_pool.update(sql.format(status, pay_type, out_trade_no))
    raise gen.Return(1)


@gen.coroutine
def save_wechat_pay_log(resultdict):
    sql = (
        "insert into pay_wx_notify (openid, trade_type, return_code, nonce_str, is_subscribe,"
        "fee_type, bank_type, phone, mch_id, out_trade_no, transaction_id, time_end, appid,"
        u"cash_fee, total_fee, result_code) values ('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}',"
        u"'{}', '{}', '{}', '{}', '{}', '{}')"
    )
    yield mysql_app_pool.insert_one(sql.format(
        resultdict['openid'], resultdict['trade_type'], resultdict['return_code'], resultdict['nonce_str'],
        resultdict['is_subscribe'], resultdict['fee_type'], resultdict['bank_type'], resultdict['attach'].split(',')[0],
        resultdict['mch_id'], resultdict['out_trade_no'], resultdict['transaction_id'], resultdict['time_end'],
        resultdict['appid'], resultdict['cash_fee'], resultdict['total_fee'], resultdict['result_code']
    ))
    raise gen.Return(1)


@gen.coroutine
def save_ali_pay_log(resultdict):
    sql = (
        "insert into pay_ali_notify (seller_email, version, app_id, buyer_pay_amount, point_amount,"
        "subject, buyer_logon_id, gmt_create, out_trade_no, invoice_amount, auth_app_id, phone, fund_bill_list,"
        "receipt_amount, trade_status, gmt_payment, trade_no, seller_id, total_amount, notify_time,"
        "notify_id, notify_type, buyer_id) values ('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}',"
        "'{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}')"
    )
    yield mysql_app_pool.insert_one(sql.format(
        resultdict['seller_email'][0], resultdict['version'][0], resultdict['app_id'][0],
        resultdict['buyer_pay_amount'][0], resultdict['point_amount'][0], resultdict['subject'][0],
        resultdict['buyer_logon_id'][0], resultdict['gmt_create'][0], resultdict['out_trade_no'][0],
        resultdict['invoice_amount'][0], resultdict['auth_app_id'][0], resultdict['body'][0],
        resultdict['fund_bill_list'][0], resultdict['receipt_amount'][0], resultdict['trade_status'][0],
        resultdict['gmt_payment'][0], resultdict['trade_no'][0], resultdict['seller_id'][0],
        resultdict['total_amount'][0], resultdict['notify_time'][0], resultdict['notify_id'][0],
        resultdict['notify_type'][0], resultdict['buyer_id'][0]
    ))
    raise gen.Return(1)


@gen.coroutine
def get_openid_with_code(code):
    url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={}&secret={}&code={}&grant_type=authorization_code"
    info = yield get_request_data(object, url.format(PAY_TYPE['gzh']['appid'], PAY_TYPE['gzh']['appsecret'], code))
    print info
    res = info['openid'] if info and 'openid' in info.keys() else ''
    raise gen.Return(res)


@gen.coroutine
def get_order_price(order_type):
    sql = "select * from order_price where order_type = '{}'"
    res = yield mysql_app_pool.get_one(sql.format(order_type), cursor='dict')
    raise gen.Return(res)


def create_id_code():
    seed = "1234567890"
    sa = []
    for i in range(6):
        sa.append(random.choice(seed))
    id_code = ''.join(sa)
    return id_code


@gen.coroutine
def send_id_code_msg_to_phone(phone, id_code):
    print id_code
    raise gen.Return(1)


@gen.coroutine
def save_id_code_to_mysql(phone, id_code):
    current_time = timetool.get_timestamp()
    sql = "insert into identifying_code (phone, id_code, pubtime) values (" \
          "'{}', '{}', {})"
    res = yield mysql_app_pool.insert_one(sql.format(phone, id_code, current_time))
    raise gen.Return(res)


@gen.coroutine
def get_last_id_code_with_phone(phone):
    current_time = timetool.get_timestamp()
    sql = "select * from identifying_code where phone = '{}' and pubtime >= {} order by pubtime desc limit 1"
    res = yield mysql_app_pool.get_one(sql.format(phone, current_time - 600), cursor='dict')
    raise gen.Return(res)